package com.ouroboroswiki.core;

import java.util.ArrayList;
import java.util.List;

public class ContentPath {
	
	private static final List<ContentPath> asList(ContentPath p) {
		ArrayList<ContentPath> result;
		if( p != null ) {
			result = new ArrayList<ContentPath>(1);
			result.add(p);
		} else {
			result = null;
		}
		return result;
	}
	
	private boolean contextualBreak;
	private List<ContentPath> children;
	private String name;
	
	public ContentPath( String name ) {
		this( name, null );
	}
	
	public ContentPath( String name, ContentPath child ) {
		this( name, child, false );
	}
	
	public ContentPath( String name, ContentPath child, boolean contextualBreak ) {
		this( name, asList(child), contextualBreak );		
	}
	
	public ContentPath( String name, List<ContentPath> children, boolean contextualBreak ) {
		this.name = name;
		this.children = children;
		this.contextualBreak = contextualBreak;
	}
	
	public String getName() {
		return this.name;
	}
	
	public List<ContentPath> getChildren() {
		return this.children;
	}
	
	public ContentPath getOnlyChild() {
		ContentPath result;
		if( this.children == null || this.children.size() == 0 ) {
			result = null;
		} else if( this.children.size() == 1 ) {
			result = this.children.get(0);
		} else {
			throw new IllegalStateException("has "+this.children.size()+" children");
		}
		return result;
	}
	
	public List<ContentPath> getNextContext() {
		ContentPath childPath = this;
		while( !childPath.isContextualBreak() && childPath != null) {
			//TODO: treat anything with multiple children as a context break
			childPath = childPath.getOnlyChild();
		}
		List<ContentPath> result;
		if( childPath != null ) {
			result = childPath.getChildren();
		} else {
			result = null;
		}
		return result;
	}	
	
	public boolean isContextualBreak() {
		return this.contextualBreak;
	}
	
	public List<ContentPath> getBasePaths() {
		return getBasePaths( new ArrayList<ContentPath>() );
	}
	
	protected List<ContentPath> getBasePaths( List<ContentPath> paths ) { 
		List<ContentPath> children = this.getChildren();
		if( children != null && children.size() > 0 ) {
			for( int i=0; i<children.size(); i++ ) {
				ContentPath child = children.get( i );
				child.getBasePaths( paths );
			}
		} else {
			paths.add( this );
		}
		return paths;		
		
	}
	
	public ContentPath getBasePath() {
		List<ContentPath> basePaths = getBasePaths();
		switch( basePaths.size() ) {
		case 0:
			return null;
		case 1:
			return basePaths.get(0);
		default:
			throw new IllegalStateException("multiple children "+this);
		}
	}
	
	public List<String> getBaseNames() {
		List<ContentPath> basePaths = this.getBasePaths();
		ArrayList<String> result = new ArrayList<String>( basePaths.size() );
		for( int i=0; i<basePaths.size(); i++ ) {
			ContentPath basePath = basePaths.get(i);
			result.add( basePath.getName() );
		}
		return result;
	}
	
	public String getBaseName() {
		return getBasePath().getName();
	}
	
	public String toString() {
		return ContentUtil.toString(this);
	}
}
